package com.guochenglang.www.web.servlet;

import com.alibaba.fastjson.JSON;
import com.guochenglang.www.controller.UserController;
import com.guochenglang.www.util.MyDependency;
import com.guochenglang.www.util.error.MyExceptionHandler;
import com.guochenglang.www.web.result.Result;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.PathParam;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 只使用一个servlet实现请求路径转发
 *
 * @author GuoChenglang
 */
@WebServlet("/method/*")
public class OnlyServlet extends HttpServlet {

    /**
     * 记录servlet异常
     */
    private static final Logger LOGGER = LogManager.getLogger(OnlyServlet.class);

    @Override
    public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("text/json;charset=UTF-8");
        //获取请求路径
        String uri = req.getRequestURI();
        //获取最后一段路径
        int index = uri.lastIndexOf('/');
        //方法名称
        System.out.println(uri);
        //获得对应Controller层的全类名
        String controllerName = getControllerName(uri.substring(getProjectPath("method").length(), index));
        String methodName = uri.substring(index + 1);
        //获取Servlet字节码对象
        try {
            //获得Controller层的字节码文件
            Class<?> aClass = Class.forName(controllerName);
            Object controller = MyDependency.returnObject(aClass);
            //获得需要执行的方法
            Method method = aClass.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //执行方法,获得Result
            Parameter[] parameters = method.getParameters();
            Object object = method.invoke(controller, req, resp);
            if (object instanceof Result) {
                Result result = (Result) object;
                //返回Result
                System.out.println("result:    " + result.getMsg());
                resp.getWriter().write(JSON.toJSONString(result));
            }
        } catch (Exception e) {
            //记录servlet异常
            LOGGER.error("发生异常！异常为{} 异常栈为", e, e);
            //统一处理Controller层的异常
            resp.getWriter().write(JSON.toJSONString(Result.error(e.toString())));
        }
    }

    /**
     * 获得Controller层全类名
     *
     * @param url 转发业务类型
     * @return Controller层全类名
     */
    private static String getControllerName(String url) {
        //获得业务类型
        StringBuilder stringBuilder = new StringBuilder(url);
        char c = (char) (stringBuilder.charAt(0) + 'A' - 'a');
        stringBuilder.setCharAt(0, c);
        //拼接Controller
        stringBuilder.append("Controller");
        //获得一个Controller的全类名
        String controllerName = UserController.class.getName();
        //获得前缀目录
        int forIndex = controllerName.lastIndexOf('.');
        //拼接
        return controllerName.substring(0, forIndex + 1) + stringBuilder.toString();
    }

    /**
     * 获得完整路径
     *
     * @param method servlet路径
     * @return 完整路径
     */
    private static String getProjectPath(String method) {
        //获得完整项目路径
        String allName = System.getProperty("user.dir");
        //获得改项目名称
        String[] projects = allName.split("\\\\");
        String projectPath = projects[projects.length - 1];
        //合成完整路径
        return "/" + projectPath + "/" + method + "/";
    }
}
